#include "PWMI_Config.h"  // 包含PWMI模块头文件，声明引脚/定时器宏定义及函数接口

/**
    ******************************************************************************
    * @brief  配置定时器为PWMI（PWM Input）模式，实现PWM信号频率和占空比的同步测量
    * @param  无
    * @retval 无
    * @note   核心机制：通过定时器的两个通道（主通道+互补通道）分别捕获PWM的上升沿和下降沿，
    *         主通道测周期（频率），互补通道测高电平时间（占空比）。
    *         硬件映射：
    *           - 输入引脚：由PWMI_PORT（如GPIOA）和PWMI_PIN（如PA6）指定，对应定时器通道1
    *           - 定时器：由TIMx（如TIM3）指定，使用内部时钟（72MHz）
    *         测量参数：
    *           - 频率范围：~15Hz（最小）至~1MHz（最大）
    *           - 占空比范围：0%~100%，精度取决于PWM周期（周期越大精度越高）
    ******************************************************************************
*/
void PWMI_Config(void)
{
    // 1. 使能输入引脚所在GPIO端口的时钟
    // PWMI_CLK为宏定义（如RCC_APB2Periph_GPIOA），控制GPIO端口的时钟使能
    // 必须先使能时钟，GPIO配置才能生效
    RCC_APB2PeriphClockCmd(PWMI_CLK, ENABLE);

    // 2. 配置输入引脚为上拉输入模式
    GPIO_InitTypeDef GPIO_InitStructure = {
        .GPIO_Mode  = GPIO_Mode_IPU,    // 上拉输入模式：
                                        // - 内部集成上拉电阻，无信号时引脚默认高电平
                                        // - 适配PWM信号的"高/低"电平特性，避免悬空干扰
        .GPIO_Pin   = PWMI_PIN,         // 输入引脚（如GPIO_Pin_6，即PA6）
                                        // 该引脚需与定时器通道1复用（如TIM3_CH1）
        .GPIO_Speed = GPIO_Speed_50MHz, // 输入模式下"速度"参数无效（仅输出模式有效）
                                        // 此处为默认配置，不影响功能
    };
    // 初始化GPIO端口（如GPIOA），应用上述配置
    GPIO_Init(PWMI_PORT, &GPIO_InitStructure);  // PWMI_PORT为宏定义（如GPIOA）

    // 3. 使能定时器时钟
    // TIM_CLK为宏定义（如RCC_APB1Periph_TIM3），对应定时器的时钟使能位
    // 定时器挂载在APB1总线，时钟使能需用RCC_APB1PeriphClockCmd函数
    RCC_APB1PeriphClockCmd(TIM_CLK, ENABLE);

    // 4. 配置定时器使用内部时钟源
    // 内部时钟路径：SYSCLK(72MHz) → AHB总线（不分频） → APB1总线（分频2） → 定时器时钟(72MHz)
    // 该函数会将TIMx的时钟源设置为内部时钟（默认也是内部时钟，显式配置更清晰）
    TIM_InternalClockConfig(TIMx);  // TIMx为宏定义（如TIM3）

    // 5. 配置定时器时基单元（决定计数频率和范围）
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruce = {
        .TIM_ClockDivision      = TIM_CKD_DIV1,    // 时钟分频因子：不分频
                                                 // 作用：定时器工作时钟与采样时钟的比例（仅影响输入滤波）
                                                 // 此处设为1:1，不影响捕获精度
        .TIM_CounterMode        = TIM_CounterMode_Up,  // 计数模式：向上计数（0→ARR→0循环）
        .TIM_Period             = 65536 - 1,       // 自动重载值（ARR=65535）
                                                 // 含义：计数器最大计数值为65535，配合1MHz计数频率
                                                 // 最大测量周期=65535×1μs≈65.5ms（对应最小频率≈15Hz）
        .TIM_Prescaler          = 72 - 1,          // 预分频器值（PSC=71）
                                                 // 计数频率=定时器时钟/(PSC+1)=72MHz/72=1MHz
                                                 // 即：每个计数单位=1μs（时间精度1μs）
        .TIM_RepetitionCounter  = 0,               // 重复计数器：仅高级定时器（如TIM1）有效
                                                 // 通用定时器（如TIM3）无此功能，必须设为0
    };
    // 将时基参数写入定时器寄存器（如TIM3的PSC、ARR等寄存器）
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStruce);

    // 6. 配置PWMI模式的基础参数（基于通道1）
    TIM_ICInitTypeDef TIM_ICInitStructure = {
        .TIM_Channel        = TIM_Channel_1,       // 主通道：通道1（如TIM3_CH1）
        .TIM_ICFilter       = 0xF,                 // 输入滤波系数：0xF（最大滤波等级）
                                                 // 滤波原理：连续采样8次（STM32F10x系列），仅当8次电平一致时
                                                 // 确认边沿有效，可滤除短于4个采样周期的噪声
        .TIM_ICPolarity     = TIM_ICPolarity_Rising,  // 主通道捕获极性：上升沿触发
        .TIM_ICPrescaler    = TIM_ICPSC_DIV1,      // 输入分频：不分频（每个有效边沿都捕获）
                                                 // 若设为DIV2，则每2个边沿捕获1次
        .TIM_ICSelection    = TIM_ICSelection_DirectTI,  // 信号映射：TI1直接连接到IC1
                                                 // 即：外部引脚信号直接送入通道1捕获单元
    };
    // 配置PWMI模式：
    // 函数内部逻辑：
    // 1. 按上述参数配置通道1（主通道，上升沿捕获）
    // 2. 自动配置通道2（互补通道）：
    //    - 捕获极性：下降沿（与通道1相反）
    //    - 信号映射：TI1间接连接到IC2（共享同一输入引脚）
    //    - 其他参数（滤波、分频）与通道1一致
    // 结果：通道1测周期，通道2测高电平时间，实现PWM全参数测量
    TIM_PWMIConfig(TIMx, &TIM_ICInitStructure);

    // 7. 配置定时器触发源为通道1的滤波后信号（TI1FP1）
    // TI1FP1：经过滤波和极性选择后的通道1输入信号
    // 作用：将通道1的上升沿作为定时器的触发信号
    TIM_SelectInputTrigger(TIMx, TIM_TS_TI1FP1);

    // 8. 配置定时器从模式为"复位模式"
    // 从模式逻辑：当检测到触发信号（TI1FP1的上升沿）时，立即将计数器（CNT）清零
    // 优势：每次上升沿都作为周期起点，确保周期测量的连续性（无需软件清零）
    TIM_SelectSlaveMode(TIMx, TIM_SlaveMode_Reset);

    // 9. 启动定时器计数器
    // 置位TIMx->CR1寄存器的CEN位（Counter Enable），计数器开始计数
    // 此时，定时器开始监测输入信号的边沿并执行捕获操作
    TIM_Cmd(TIMx, ENABLE);
}

/**
    ******************************************************************************
    * @brief  计算输入PWM信号的频率
    * @param  无
    * @retval 频率值（单位：Hz）
    * @note   测量原理：频率 = 1 / 周期，其中"周期"由通道1的捕获值计算。
    *         通道1捕获值（CCR1）：两个相邻上升沿之间的计数次数（单位：μs）。
    *         公式推导：
    *           周期T = (CCR1 + 1) × 1μs（+1是因为计数从0开始）
    *           频率f = 1 / T = 1e6 / (CCR1 + 1) Hz（1e6=1000000，将μs转换为秒）
    *         示例：若CCR1=999 → T=1000μs → f=1000Hz。
    ******************************************************************************
*/
u32 PWMI_GetFreq(void)
{
    // 读取通道1捕获寄存器（TIMx->CCR1）的值
    // 该值为两个相邻上升沿之间的计数次数（单位：μs）
    // 计算并返回频率（单位：Hz）
    return (1000000 / (TIM_GetCapture1(TIMx) + 1));
}

/**
    ******************************************************************************
    * @brief  计算输入PWM信号的占空比
    * @param  无
    * @retval 占空比（单位：%，范围0~100）
    * @note   测量原理：占空比 = （高电平时间 / 周期）× 100%。
    *         高电平时间：通道2捕获值（CCR2）+1（单位：μs），对应上升沿到下降沿的时间。
    *         周期：通道1捕获值（CCR1）+1（单位：μs），对应两个上升沿的间隔。
    *         公式：占空比 = [(CCR2 + 1) / (CCR1 + 1)] × 100%。
    *         示例：CCR2=499，CCR1=999 → 占空比=50%。
    ******************************************************************************
*/
u32 PWMI_GetDuty(void)
{
    // 读取通道2捕获寄存器（TIMx->CCR2）的值（高电平时间的计数次数）
    // 读取通道1捕获寄存器的值（周期的计数次数）
    // 计算并返回占空比（单位：%）
    return ((TIM_GetCapture2(TIMx) + 1) * 100 / (TIM_GetCapture1(TIMx) + 1));
}
